home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / mysql / sql-bench / test-insert < prev    next >
Encoding:
Text File  |  2006-04-26  |  49.5 KB  |  1,802 lines

  1. #!/usr/bin/perl
  2. # Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  3. #
  4. # This library is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU Library General Public
  6. # License as published by the Free Software Foundation; either
  7. # version 2 of the License, or (at your option) any later version.
  8. #
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. # Library General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Library General Public
  15. # License along with this library; if not, write to the Free
  16. # Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  17. # MA 02111-1307, USA
  18. #
  19. # Test of creating a simple table and inserting $record_count records in it,
  20. # $opt_loop_count rows in order, $opt_loop_count rows in reverse order and
  21. # $opt_loop_count rows in random order
  22. #
  23. # changes made for Oracle compatibility
  24. # - $limits->{'func_odbc_mod'} is OK from crash-me, but it fails here so set we
  25. #   set it to 0 in server-cfg
  26. # - the default server config runs out of rollback segments, so we added a
  27. #   couple of disconnect/connects to reset
  28. #
  29. ##################### Standard benchmark inits ##############################
  30.  
  31. use Cwd;
  32. use DBI;
  33. use Benchmark;
  34. use Data::Dumper;
  35.  
  36. $opt_loop_count=100000;        # number of rows/3
  37. $small_loop_count=10;        # Loop for full table retrieval
  38. $range_loop_count=$small_loop_count*50;
  39. $many_keys_loop_count=$opt_loop_count;
  40. $opt_read_key_loop_count=$opt_loop_count;
  41.  
  42. $pwd = cwd(); $pwd = "." if ($pwd eq '');
  43. require "$pwd/bench-init.pl" || die "Can't read Configuration file: $!\n";
  44.  
  45. if ($opt_small_test)
  46. {
  47.   $opt_loop_count/=100;
  48.   $many_keys_loop_count=$opt_loop_count/10;
  49.   $range_loop_count=10;
  50.   $opt_read_key_loop_count=10;
  51. }
  52. elsif ($opt_small_tables)
  53. {
  54.   $opt_loop_count=10000;        # number of rows/3
  55.   $many_keys_loop_count=$opt_loop_count;
  56.   $opt_read_key_loop_count=10;
  57. }
  58. elsif ($opt_small_key_tables)
  59. {
  60.   $many_keys_loop_count/=10;
  61. }
  62.  
  63. if ($opt_loop_count < 100)
  64. {
  65.   $opt_loop_count=100;        # Some tests must have some data to work!
  66. }
  67. $range_loop_count=min($opt_loop_count,$range_loop_count);
  68.  
  69.  
  70. print "Testing the speed of inserting data into 1 table and do some selects on it.\n";
  71. print "The tests are done with a table that has $opt_loop_count rows.\n\n";
  72.  
  73. ####
  74. #### Generating random keys
  75. ####
  76.  
  77. print "Generating random keys\n";
  78. $random[$opt_loop_count]=0;
  79. for ($i=0 ; $i < $opt_loop_count ; $i++)
  80. {
  81.   $random[$i]=$i+$opt_loop_count;
  82. }
  83.  
  84. my $tmpvar=1;
  85. for ($i=0 ; $i < $opt_loop_count ; $i++)
  86. {
  87.   $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  88.   $swap=$tmpvar % $opt_loop_count;
  89.   $tmp=$random[$i]; $random[$i]=$random[$swap]; $random[$swap]=$tmp;
  90. }
  91.  
  92. $total_rows=$opt_loop_count*3;
  93.  
  94. ####
  95. ####  Connect and start timeing
  96. ####
  97. $start_time=new Benchmark;
  98. $dbh = $server->connect();
  99. ####
  100. #### Create needed tables
  101. ####
  102.  
  103. goto keys_test if ($opt_stage == 2);
  104. goto select_test if ($opt_skip_create);
  105.  
  106. print "Creating tables\n";
  107. $dbh->do("drop table bench1" . $server->{'drop_attr'});
  108. $dbh->do("drop table bench2" . $server->{'drop_attr'});
  109. $dbh->do("drop table bench3" . $server->{'drop_attr'});
  110. do_many($dbh,$server->create("bench1",
  111.                  ["id int NOT NULL",
  112.                   "id2 int NOT NULL",
  113.                   "id3 int NOT NULL",
  114.                   "dummy1 char(30)"],
  115.                  ["primary key (id,id2)",
  116.                  "index ix_id3 (id3)"]));
  117.  
  118. if ($opt_lock_tables)
  119. {
  120.   $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  121. }
  122.  
  123. ####
  124. #### Insert $total_rows records in order, in reverse order and random.
  125. ####
  126.  
  127. $loop_time=new Benchmark;
  128.  
  129. if ($opt_fast_insert)
  130. {
  131.   $query="insert into bench1 values ";
  132. }
  133. else
  134. {
  135.   $query="insert into bench1 (id,id2,id3,dummy1) values ";
  136. }
  137.  
  138. if ($opt_fast && $server->{transactions})
  139. {
  140.   $dbh->{AutoCommit} = 0;
  141.   print "Transactions enabled\n" if ($opt_debug);
  142. }
  143.  
  144. if (($opt_fast || $opt_fast_insert) && $server->{'limits'}->{'insert_multi_value'})
  145. {
  146.   $query_size=$server->{'limits'}->{'query_size'};
  147.  
  148.   print "Inserting $opt_loop_count multiple-value rows in order\n";
  149.   $res=$query;
  150.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  151.   {
  152.     $tmp= "($i,$i,$i,'ABCDEFGHIJ'),";
  153.     if (length($tmp)+length($res) < $query_size)
  154.     {
  155.       $res.= $tmp;
  156.     }
  157.     else
  158.     {
  159.       $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  160.       $res=$query . $tmp;
  161.     }
  162.   }
  163.   print "Inserting $opt_loop_count multiple-value rows in reverse order\n";
  164.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  165.   {
  166.     $tmp= "(" . ($total_rows-1-$i) . "," .($total_rows-1-$i) .
  167.       "," .($total_rows-1-$i) . ",'BCDEFGHIJK'),";
  168.     if (length($tmp)+length($res) < $query_size)
  169.     {
  170.       $res.= $tmp;
  171.     }
  172.     else
  173.     {
  174.       $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  175.       $res=$query . $tmp;
  176.     }
  177.   }
  178.   print "Inserting $opt_loop_count multiple-value rows in random order\n";
  179.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  180.   {
  181.     $tmp= "(" . $random[$i] . "," . $random[$i] . "," . $random[$i] .
  182.       ",'CDEFGHIJKL')," or die $DBI::errstr;
  183.     if (length($tmp)+length($res) < $query_size)
  184.     {
  185.       $res.= $tmp;
  186.     }
  187.     else
  188.     {
  189.       $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  190.       $res=$query . $tmp;
  191.     }
  192.   }
  193.   $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  194. }
  195. else
  196. {
  197.   print "Inserting $opt_loop_count rows in order\n";
  198.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  199.   {
  200.     $sth = $dbh->do($query . "($i,$i,$i,'ABCDEFGHIJ')") or die $DBI::errstr;
  201.   }
  202.  
  203.   print "Inserting $opt_loop_count rows in reverse order\n";
  204.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  205.   {
  206.     $sth = $dbh->do($query . "(" . ($total_rows-1-$i) . "," .
  207.             ($total_rows-1-$i) . "," .
  208.             ($total_rows-1-$i) . ",'BCDEFGHIJK')")
  209.       or die $DBI::errstr;
  210.   }
  211.  
  212.   print "Inserting $opt_loop_count rows in random order\n";
  213.  
  214.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  215.   {
  216.     $sth = $dbh->do($query . "(". $random[$i] . "," . $random[$i] .
  217.             "," . $random[$i] . ",'CDEFGHIJKL')") or die $DBI::errstr;
  218.   }
  219. }
  220.  
  221. if ($opt_fast && $server->{transactions})
  222. {
  223.   $dbh->commit;
  224.   $dbh->{AutoCommit} = 1;
  225. }
  226.  
  227. $end_time=new Benchmark;
  228. print "Time for insert (" . ($total_rows) . "): " .
  229.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  230.  
  231. if ($opt_lock_tables)
  232. {
  233.   $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
  234. }
  235. if ($opt_fast && defined($server->{vacuum}))
  236. {
  237.   $server->vacuum(1,\$dbh,"bench1");
  238. }
  239. if ($opt_lock_tables)
  240. {
  241.   $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  242. }
  243.  
  244. ####
  245. #### insert $opt_loop_count records with duplicate id
  246. ####
  247.  
  248. if ($limits->{'unique_index'})
  249. {
  250.   print "Testing insert of duplicates\n";
  251.   $loop_time=new Benchmark;
  252.  
  253.   if ($opt_fast && $server->{transactions})
  254.   {
  255.     $dbh->{AutoCommit} = 0;
  256.   }
  257.  
  258.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  259.   {
  260.     $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  261.     $tmp=$tmpvar % ($total_rows);
  262.     $tmpquery = "$query ($tmp,$tmp,2,'D')";
  263.     if ($dbh->do($tmpquery))
  264.     {
  265.       die "Didn't get an error when inserting duplicate record $tmp\n";
  266.     }
  267.   }
  268.   if ($opt_fast && $server->{transactions})
  269.   {
  270.     $dbh->commit;
  271.     $dbh->{AutoCommit} = 1;
  272.   }
  273.  
  274.   $end_time=new Benchmark;
  275.   print "Time for insert_duplicates (" . ($opt_loop_count) . "): " .
  276.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  277. }
  278.  
  279.  
  280. ####
  281. #### Do some selects on the table
  282. ####
  283.  
  284. select_test:
  285.  
  286. # ----------------- prepared+executed/prepared*executed tests
  287.  
  288. print "Test of prepared+execute/once prepared many execute selects\n";
  289. $loop_time=new Benchmark;
  290.  
  291. for ($i=1 ; $i <= $opt_loop_count ; $i++)
  292. {
  293.   my ($key_value)=$random[$i];
  294.   my ($query)= "select * from bench1 where id=$key_value";  
  295.   print "$query\n" if ($opt_debug);
  296.   $sth = $dbh->prepare($query);
  297.   if (! $sth)
  298.     {
  299.       die "error in prepare select with id = $key_value : $DBI::errstr";
  300.     };
  301.   if (! $sth->execute)  
  302.    {
  303.       die "cannot execute prepare select with id = $key_value : $DBI::errstr";      
  304.    }
  305.   while ($sth->fetchrow_arrayref) { };      
  306.   $sth->finish;
  307. };
  308. $end_time=new Benchmark;
  309. print "Time for prepared_select ($opt_loop_count): " .
  310.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  311.  
  312. $loop_time=new Benchmark;
  313. $query= "select * from bench1 where id=?";  
  314. $sth = $dbh->prepare($query);
  315. if (! $sth)
  316. {
  317.   die "cannot prepare select: $DBI::errstr";
  318. };
  319.  
  320. for ($i=1 ; $i <= $opt_loop_count ; $i++)
  321. {
  322.   my ($key_value)=$random[$i];
  323.   $sth->bind_param(1,$key_value);
  324.   print "$query , id = $key_value\n" if ($opt_debug);
  325.   if (! $sth->execute)  
  326.    {
  327.       die "cannot execute prepare select with id = $key_value : $DBI::errstr";      
  328.    }
  329.   while ($sth->fetchrow_arrayref) { };      
  330. };
  331. $sth->finish;
  332. $end_time=new Benchmark;
  333. print "Time for once_prepared_select ($opt_loop_count): " .
  334.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  335.  
  336.  
  337. print "Retrieving data from the table\n";
  338. $loop_time=new Benchmark;
  339. $error=0;
  340.  
  341. # It's really a small table, so we can try a select on everything
  342.  
  343. $count=0;
  344. for ($i=1 ; $i <= $small_loop_count ; $i++)
  345. {
  346.   if (($found_rows=fetch_all_rows($dbh,"select id from bench1")) !=
  347.       $total_rows)
  348.   {
  349.     if (!$error++)
  350.     {
  351.       print "Warning: Got $found_rows rows when selecting a whole table of " . ($total_rows) . " rows\nContact the database or DBD author!\n";
  352.     }
  353.   }
  354.   $count+=$found_rows;
  355. }
  356.  
  357. $end_time=new Benchmark;
  358. print "Time for select_big ($small_loop_count:$count): " .
  359.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  360.  
  361. #
  362. # Do a lot of different ORDER BY queries
  363. #
  364.  
  365. $loop_time=new Benchmark;
  366. $estimated=$rows=0;
  367. for ($i=1 ; $i <= $small_loop_count ; $i++)
  368. {
  369.   $rows+=fetch_all_rows($dbh,"select id,id2 from bench1 order by id,id2",1);
  370.   $end_time=new Benchmark;
  371.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  372.                      $small_loop_count));
  373. }
  374. if ($estimated)
  375. { print "Estimated time"; }
  376. else
  377. { print "Time"; }
  378. print " for order_by_big_key ($small_loop_count:$rows): " .
  379.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  380.  
  381.  
  382. $loop_time=new Benchmark;
  383. $estimated=$rows=0;
  384. for ($i=1 ; $i <= $small_loop_count ; $i++)
  385. {
  386.   $rows+=fetch_all_rows($dbh,"select id,id2 from bench1 order by id desc, id2 desc",1);
  387.   $end_time=new Benchmark;
  388.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  389.                      $small_loop_count));
  390. }
  391. if ($estimated)
  392. { print "Estimated time"; }
  393. else
  394. { print "Time"; }
  395. print " for order_by_big_key_desc ($small_loop_count:$rows): " .
  396.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  397.  
  398.  
  399. $loop_time=new Benchmark;
  400. $estimated=$rows=0;
  401. for ($i=1 ; $i <= $small_loop_count ; $i++)
  402. {
  403.   $rows+=fetch_all_rows($dbh,"select id from bench1 order by id desc",1);
  404.   $end_time=new Benchmark;
  405.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  406.                      $small_loop_count));
  407. }
  408. if ($estimated)
  409. { print "Estimated time"; }
  410. else
  411. { print "Time"; }
  412. print " for order_by_big_key_prefix ($small_loop_count:$rows): " .
  413.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  414.  
  415.  
  416. $loop_time=new Benchmark;
  417. $estimated=$rows=0;
  418. for ($i=1 ; $i <= $small_loop_count ; $i++)
  419. {
  420.   $rows+=fetch_all_rows($dbh,"select id3 from bench1 order by id3",1);
  421.   $end_time=new Benchmark;
  422.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  423.                      $small_loop_count));
  424. }
  425. if ($estimated)
  426. { print "Estimated time"; }
  427. else
  428. { print "Time"; }
  429. print " for order_by_big_key2 ($small_loop_count:$rows): " .
  430.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  431.  
  432.  
  433. $sel=$limits->{'order_by_unused'} ? "id2" : "*";
  434. $loop_time=new Benchmark;
  435. $estimated=$rows=0;
  436. for ($i=1 ; $i <= $small_loop_count ; $i++)
  437. {
  438.   $rows+=fetch_all_rows($dbh,"select $sel from bench1 order by id3",1);
  439.   $end_time=new Benchmark;
  440.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  441.                      $small_loop_count));
  442. }
  443. if ($estimated)
  444. { print "Estimated time"; }
  445. else
  446. { print "Time"; }
  447. print " for order_by_big_key_diff ($small_loop_count:$rows): " .
  448.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  449.  
  450.  
  451. $sel=$limits->{'order_by_unused'} ? "id" : "*";
  452. $loop_time=new Benchmark;
  453. $estimated=$rows=0;
  454. for ($i=1 ; $i <= $small_loop_count ; $i++)
  455. {
  456.   $rows+=fetch_all_rows($dbh,"select $sel from bench1 order by id2,id3",1);
  457.   $end_time=new Benchmark;
  458.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  459.                      $small_loop_count));
  460. }
  461. if ($estimated)
  462. { print "Estimated time"; }
  463. else
  464. { print "Time"; }
  465. print " for order_by_big ($small_loop_count:$rows): " .
  466.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  467.  
  468.  
  469. $sel=$limits->{'order_by_unused'} ? "dummy1" : "dummy1,id3";
  470. $loop_time=new Benchmark;
  471. $estimated=$rows=0;
  472. for ($i=1 ; $i <= $range_loop_count ; $i++)
  473. {
  474.   $start=$opt_loop_count/$range_loop_count*$i;
  475.   $end=$start+$i;
  476.   $rows+=fetch_all_rows($dbh,"select $sel from bench1 where id>=$start and id <= $end order by id3",1);
  477.   $end_time=new Benchmark;
  478.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  479.                      $range_loop_count));
  480. }
  481. if ($estimated)
  482. { print "Estimated time"; }
  483. else
  484. { print "Time"; }
  485. print " for order_by_range ($range_loop_count:$rows): " .
  486.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  487.  
  488. $sel=$limits->{'order_by_unused'} ? "dummy1" : "dummy1,id";
  489. $loop_time=new Benchmark;
  490. $estimated=$rows=0;
  491. for ($i=1 ; $i <= $range_loop_count ; $i++)
  492. {
  493.   $start=$opt_loop_count/$range_loop_count*$i;
  494.   $end=$start+$i;
  495.   $rows+=fetch_all_rows($dbh,"select $sel from bench1 where id>=$start and id <= $end order by id",1);
  496.   $end_time=new Benchmark;
  497.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  498.                      $range_loop_count));
  499. }
  500. if ($estimated)
  501. { print "Estimated time"; }
  502. else
  503. { print "Time"; }
  504. print " for order_by_key_prefix ($range_loop_count:$rows): " .
  505.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  506.  
  507. $sel=$limits->{'order_by_unused'} ? "id2" : "id2,id3";
  508. $loop_time=new Benchmark;
  509. $estimated=$rows=0;
  510. for ($i=1 ; $i <= $range_loop_count ; $i++)
  511. {
  512.   $start=$opt_loop_count/$range_loop_count*$i;
  513.   $end=$start+$range_loop_count;
  514.   $rows+=fetch_all_rows($dbh,"select $sel from bench1 where id3>=$start and id3 <= $end order by id3",1);
  515.   $end_time=new Benchmark;
  516.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$i,
  517.                      $range_loop_count));
  518. }
  519. if ($estimated)
  520. { print "Estimated time"; }
  521. else
  522. { print "Time"; }
  523. print " for order_by_key2_diff ($range_loop_count:$rows): " .
  524.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  525.  
  526. #
  527. # Test of select on 2 different keys with or
  528. # (In this case database can only use keys if they do an automatic union).
  529. #
  530.  
  531. $loop_time=new Benchmark;
  532. $estimated=0;
  533. $rows=0;
  534. $count=0;
  535. for ($i=1 ; $i <= $range_loop_count ; $i++)
  536. {
  537.   my $rnd=$i;
  538.   my $rnd2=$random[$i];
  539.   $rows+=fetch_all_rows($dbh,"select id2 from bench1 where id=$rnd or id3=$rnd2",1);
  540.   $count++;
  541.   $end_time=new Benchmark;
  542.   last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
  543.                      $range_loop_count));
  544. }
  545. if ($estimated)
  546. { print "Estimated time"; }
  547. else
  548. { print "Time"; }
  549. print " for select_diff_key ($count:$rows): " .
  550.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  551.  
  552.  
  553. # Test select that is very popular when using ODBC
  554.  
  555. check_or_range("id","select_range_prefix");
  556. check_or_range("id3","select_range_key2");
  557.  
  558. # Check reading on direct key on id and id3
  559.  
  560. check_select_key("*","id","select_key_prefix");
  561. check_select_key2("*","id","id2","select_key");
  562. check_select_key2("id,id2","id","id2","select_key_return_key");
  563. check_select_key("*","id3","select_key2");
  564. check_select_key("id3","id3","select_key2_return_key");
  565. check_select_key("id,id2","id3","select_key2_return_prim");
  566.  
  567. ####
  568. #### A lot of simple selects on ranges
  569. ####
  570.  
  571. @Q=("select * from bench1 where !id!=3 or !id!=2 or !id!=1 or !id!=4 or !id!=16 or !id!=10",
  572.     6,
  573.     "select * from bench1 where !id!>=" . ($total_rows-1) ." or !id!<1",
  574.     2,
  575.     "select * from bench1 where !id!>=1 and !id!<=2",
  576.     2,
  577.     "select * from bench1 where (!id!>=1 and !id!<=2) or (!id!>=1 and !id!<=2)",
  578.     2,
  579.     "select * from bench1 where !id!>=1 and !id!<=10 and !id!<=5",
  580.     5,
  581.     "select * from bench1 where (!id!>0 and !id!<2) or !id!>=" . ($total_rows-1),
  582.     2,
  583.     "select * from bench1 where (!id!>0 and !id!<2) or (!id!>= " . ($opt_loop_count/2) . " and !id! <= " . ($opt_loop_count/2+2) . ") or !id! = " . ($opt_loop_count/2-1),
  584.     5,
  585.     "select * from bench1 where (!id!>=5 and !id!<=10) or (!id!>=1 and !id!<=4)",
  586.     10,
  587.     "select * from bench1 where (!id!=1 or !id!=2) and (!id!=3 or !id!=4)",
  588.     0,
  589.     "select * from bench1 where (!id!=1 or !id!=2) and (!id!=2 or !id!=3)",
  590.     1,
  591.     "select * from bench1 where (!id!=1 or !id!=5 or !id!=20 or !id!=40) and (!id!=1 or !id!>=20 or !id!=4)",
  592.     3,
  593.     "select * from bench1 where ((!id!=1 or !id!=3) or (!id!>1 and !id!<3)) and !id!<=2",
  594.     2,
  595.     "select * from bench1 where (!id! >= 0 and !id! < 4) or (!id! >=4 and !id! < 6)",
  596.     6,
  597.     "select * from bench1 where !id! <= -1 or (!id! >= 0 and !id! <= 5) or (!id! >=4 and !id! < 6) or (!id! >=6 and !id! <=7) or (!id!>7 and !id! <= 8)",
  598.     9,
  599.     "select * from bench1 where (!id!>=1 and !id!<=2 or !id!>=4 and !id!<=5) or (!id!>=0 and !id! <=10)",
  600.     11,
  601.     "select * from bench1 where (!id!>=1 and !id!<=2 or !id!>=4 and !id!<=5) or (!id!>2 and !id! <=10)",
  602.     10,
  603.     "select * from bench1 where (!id!>1 or !id! <1) and !id!<=2",
  604.     2,
  605.     "select * from bench1 where !id! <= 2 and (!id!>1 or !id! <=1)",
  606.     3,
  607.     "select * from bench1 where (!id!>=1 or !id! <1) and !id!<=2",
  608.     3,
  609.     "select * from bench1 where (!id!>=1 or !id! <=2) and !id!<=2",
  610.     3
  611.     );
  612.  
  613. print "\nTest of compares with simple ranges\n";
  614. check_select_range("id","select_range_prefix");
  615. check_select_range("id3","select_range_key2");
  616.  
  617. ####
  618. #### Some group queries
  619. ####
  620.  
  621. if ($limits->{'group_functions'})
  622. {
  623.   $loop_time=new Benchmark;
  624.   $count=1;
  625.  
  626.   $estimated=0;
  627.   for ($tests=0 ; $tests < $small_loop_count ; $tests++)
  628.   {
  629.     $sth=$dbh->prepare($query="select count(*) from bench1") or die $DBI::errstr;
  630.     $sth->execute or die $sth->errstr;
  631.     if (($sth->fetchrow_array)[0] != $total_rows)
  632.     {
  633.       print "Warning: '$query' returned wrong result\n";
  634.     }
  635.     $sth->finish;
  636.  
  637.     # min, max in keys are very normal
  638.     $count+=7;
  639.     fetch_all_rows($dbh,"select min(id) from bench1");
  640.     fetch_all_rows($dbh,"select max(id) from bench1");
  641.     fetch_all_rows($dbh,"select sum(id+0.0) from bench1");
  642.     fetch_all_rows($dbh,"select min(id3),max(id3),sum(id3-0.0) from bench1");
  643.     if ($limits->{'group_func_sql_min_str'})
  644.     {
  645.       fetch_all_rows($dbh,"select min(dummy1),max(dummy1) from bench1");
  646.     }
  647.     $count++;
  648.     $sth=$dbh->prepare($query="select count(*) from bench1 where id >= " .
  649.                ($opt_loop_count*2)) or die $DBI::errstr;
  650.     $sth->execute or die $DBI::errstr;
  651.     if (($sth->fetchrow_array)[0] != $opt_loop_count)
  652.     {
  653.       print "Warning: '$query' returned wrong result\n";
  654.     }
  655.     $sth->finish;
  656.  
  657.     $count++;
  658.     $sth=$dbh->prepare($query="select count(*),sum(id+0.0),min(id),max(id),avg(id-0.0) from bench1") or die $DBI::errstr;
  659.     $sth->execute or die $DBI::errstr;
  660.     @row=$sth->fetchrow_array;
  661.     if ($row[0] != $total_rows ||
  662.     int($row[1]+0.5) != int((($total_rows-1)/2*$total_rows)+0.5) ||
  663.     $row[2] != 0 ||
  664.     $row[3] != $total_rows-1 ||
  665.     1-$row[4]/(($total_rows-1)/2) > 0.001)
  666.     {
  667.       # PostgreSQL 6.3 fails here
  668.       print "Warning: '$query' returned wrong result: @row\n";
  669.     }
  670.     $sth->finish;
  671.  
  672.     if ($limits->{'func_odbc_mod'})
  673.     {
  674.       $tmp="mod(id,10)";
  675.       if ($limits->{'func_extra_%'})
  676.       {
  677.     $tmp="id % 10";        # For postgreSQL
  678.       }
  679.       $count++;
  680.       if ($limits->{'group_by_alias'}) {
  681.     if (fetch_all_rows($dbh,$query=$server->query("select $tmp as last_digit,count(*) from bench1 group by last_digit")) != 10)
  682.     {
  683.       print "Warning: '$query' returned wrong number of rows\n";
  684.     }
  685.       } elsif ($limits->{'group_by_position'}) {
  686.     if (fetch_all_rows($dbh,$query=$server->query("select $tmp,count(*) from bench1 group by 1")) != 10)
  687.     {
  688.       print "Warning: '$query' returned wrong number of rows\n";
  689.     }
  690.       }
  691.     }
  692.  
  693.     if ($limits->{'order_by_position'} && $limits->{'group_by_position'})
  694.     {
  695.       $count++;
  696.       if (fetch_all_rows($dbh, $query="select id,id3,dummy1 from bench1 where id < 100+$count-$count group by id,id3,dummy1 order by id desc,id3,dummy1") != 100)
  697.       {
  698.     print "Warning: '$query' returned wrong number of rows\n";
  699.       }
  700.     }
  701.     $end_time=new Benchmark;
  702.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests,
  703.                        $small_loop_count));
  704.   }
  705.   print_time($estimated);
  706.   print " for select_group ($count): " .
  707.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  708.  
  709.   $loop_time=new Benchmark;
  710.   $count=$estimated=0;
  711.   for ($tests=1 ; $tests <= $range_loop_count*5 ; $tests++)
  712.   {
  713.     $count+=6;
  714.     fetch_all_rows($dbh,"select min(id) from bench1");
  715.     fetch_all_rows($dbh,"select max(id) from bench1");
  716.     fetch_all_rows($dbh,"select min(id2) from bench1 where id=$tests");
  717.     fetch_all_rows($dbh,"select max(id2) from bench1 where id=$tests");
  718.     if ($limits->{'group_func_sql_min_str'})
  719.     {
  720.       fetch_all_rows($dbh,"select min(dummy1) from bench1 where id=$tests");
  721.       fetch_all_rows($dbh,"select max(dummy1) from bench1 where id=$tests");
  722.     }
  723.     $end_time=new Benchmark;
  724.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests,
  725.                        $range_loop_count*5));
  726.   }
  727.   if ($estimated)
  728.   { print "Estimated time"; }
  729.   else
  730.   { print "Time"; }
  731.   print " for min_max_on_key ($count): " .
  732.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  733.  
  734.   $loop_time=new Benchmark;
  735.   $count=$estimated=0;
  736.   for ($tests=1 ; $tests <= $small_loop_count ; $tests++)
  737.   {
  738.     $count+=6;
  739.     fetch_all_rows($dbh,"select min(id2) from bench1");
  740.     fetch_all_rows($dbh,"select max(id2) from bench1");
  741.     fetch_all_rows($dbh,"select min(id3) from bench1 where id2=$tests");
  742.     fetch_all_rows($dbh,"select max(id3) from bench1 where id2=$tests");
  743.     if ($limits->{'group_func_sql_min_str'})
  744.     {
  745.       fetch_all_rows($dbh,"select min(dummy1) from bench1 where id2=$tests");
  746.       fetch_all_rows($dbh,"select max(dummy1) from bench1 where id2=$tests");
  747.     }
  748.     $end_time=new Benchmark;
  749.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests,
  750.                        $range_loop_count));
  751.   }
  752.   if ($estimated)
  753.   { print "Estimated time"; }
  754.   else
  755.   { print "Time"; }
  756.   print " for min_max ($count): " .
  757.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  758.  
  759.   $loop_time=new Benchmark;
  760.   $count=0;
  761.   $total=$opt_loop_count*3;
  762.   for ($tests=0 ; $tests < $total ; $tests+=$total/100)
  763.   {
  764.     $count+=1;
  765.     fetch_all_rows($dbh,"select count(id) from bench1 where id < $tests");
  766.   }
  767.   $end_time=new Benchmark;
  768.   print "Time for count_on_key ($count): " .
  769.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  770.  
  771.   $loop_time=new Benchmark;
  772.   $count=0;
  773.   for ($tests=0 ; $tests < $total ; $tests+=$total/100)
  774.   {
  775.     $count+=1;
  776.     fetch_all_rows($dbh,"select count(dummy1) from bench1 where id2 < $tests");
  777.   }
  778.   $end_time=new Benchmark;
  779.   print "Time for count ($count): " .
  780.       timestr(timediff($end_time, $loop_time),"all") . "\n";
  781.  
  782.   if ($limits->{'group_distinct_functions'})
  783.   {
  784.     $loop_time=new Benchmark;
  785.     $count=$estimated=0;
  786.     for ($tests=1 ; $tests <= $small_loop_count ; $tests++)
  787.     {
  788.       $count+=2;
  789.       fetch_all_rows($dbh,"select count(distinct dummy1) from bench1");
  790.       fetch_all_rows($dbh,"select dummy1,count(distinct id) from bench1 group by dummy1");
  791.       $end_time=new Benchmark;
  792.       last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$tests,
  793.                          $small_loop_count));
  794.     }
  795.     if ($estimated)
  796.     { print "Estimated time"; }
  797.     else
  798.     { print "Time"; }
  799.     print " for count_distinct_big ($count): " .
  800.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  801.   }
  802. }
  803.  
  804.  
  805. if ($server->small_rollback_segment())
  806. {
  807.   $dbh->disconnect;                # close connection
  808.   $dbh = $server->connect();
  809. }
  810.  
  811. ####
  812. #### Some updates on the table
  813. ####
  814.  
  815. $loop_time=new Benchmark;
  816.  
  817. if ($limits->{'functions'})
  818. {
  819.   print "\nTesting update of keys with functions\n";
  820.   my $update_loop_count=$opt_loop_count/2;
  821.   for ($i=0 ; $i < $update_loop_count ; $i++)
  822.   {
  823.     my $tmp=$opt_loop_count+$random[$i]; # $opt_loop_count*2 <= $tmp < $total_rows
  824.     $sth = $dbh->do("update bench1 set id3=-$tmp where id3=$tmp") or die $DBI::errstr;
  825.   }
  826.  
  827.   $end_time=new Benchmark;
  828.   print "Time for update_of_key ($update_loop_count):  " .
  829.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  830.  
  831.   if ($opt_lock_tables)
  832.   {
  833.     do_query($dbh,"UNLOCK TABLES");
  834.   }
  835.   if ($opt_fast && defined($server->{vacuum}))
  836.   {
  837.     $server->vacuum(1,\$dbh,"bench1");
  838.   }
  839.   if ($opt_lock_tables)
  840.   {
  841.     $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  842.   }
  843.  
  844.   if ($server->small_rollback_segment())
  845.   {
  846.     $dbh->disconnect;                # close connection
  847.     $dbh = $server->connect();
  848.   }
  849.  
  850.   $loop_time=new Benchmark;
  851.   $count=0;
  852.   $step=int($opt_loop_count/$range_loop_count+1);
  853.   for ($i= 0 ; $i < $opt_loop_count ; $i+= $step)
  854.   {
  855.     $count++;
  856.     $sth=$dbh->do("update bench1 set id3= 0-id3 where id3 >= 0 and id3 <= $i") or die $DBI::errstr;
  857.   }
  858.  
  859.   if ($server->small_rollback_segment())
  860.   {
  861.     $dbh->disconnect;                # close connection
  862.     $dbh = $server->connect();
  863.   }
  864.   $count++;
  865.   $sth=$dbh->do("update bench1 set id3= 0-id3 where id3 >= 0 and id3 < $opt_loop_count") or die $DBI::errstr;
  866.  
  867.   if ($server->small_rollback_segment())
  868.   {
  869.     $dbh->disconnect;                # close connection
  870.     $dbh = $server->connect();
  871.   }
  872.   $count++;
  873.   $sth=$dbh->do("update bench1 set id3= 0-id3 where id3 >= $opt_loop_count and id3 < ". ($opt_loop_count*2)) or die $DBI::errstr;
  874.  
  875.   #
  876.   # Check that everything was updated
  877.   # In principle we shouldn't time this in the update loop..
  878.   #
  879.  
  880.   if ($server->small_rollback_segment())
  881.   {
  882.     $dbh->disconnect;                # close connection
  883.     $dbh = $server->connect();
  884.   }
  885.   $row_count=0;
  886.   if (($sth=$dbh->prepare("select count(*) from bench1 where id3>=0"))
  887.       && $sth->execute)
  888.   {
  889.     ($row_count)=$sth->fetchrow;
  890.   }
  891.   $result=1 + $opt_loop_count-$update_loop_count;
  892.   if ($row_count != $result)
  893.   {
  894.     print "Warning: Update check returned $row_count instead of $result\n";
  895.   }
  896.  
  897.   $sth->finish;
  898.   if ($server->small_rollback_segment())
  899.   {
  900.     $dbh->disconnect;                # close connection
  901.     $dbh = $server->connect();
  902.   }
  903.   #restore id3 to 0 <= id3 < $total_rows/10 or 0<= id3 < $total_rows
  904.  
  905.   my $func=($limits->{'func_odbc_floor'}) ? "floor((0-id3)/20)" : "0-id3";
  906.   $count++;
  907.   $sth=$dbh->do($query="update bench1 set id3=$func where id3<0") or die $DBI::errstr;
  908.  
  909.   $end_time=new Benchmark;
  910.   print "Time for update_of_key_big ($count): " .
  911.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  912. }
  913. else
  914. {
  915.   print "\nTesting update of keys in loops\n";
  916.   #
  917.   # This is for mSQL that doesn't have functions. Do we really need this ????
  918.   #
  919.  
  920.   $sth=$dbh->prepare("select id3 from bench1 where id3 >= 0") or die $DBI::errstr;
  921.   $sth->execute or die $DBI::errstr;
  922.   $count=0;
  923.   while (@tmp = $sth->fetchrow_array)
  924.   {
  925.     my $tmp1 = "-$tmp[0]";
  926.     my $sth1 = $dbh->do("update bench1 set id3 = $tmp1 where id3 = $tmp[0]");
  927.     $count++;
  928.     $end_time=new Benchmark;
  929.     if (($end_time->[0] - $loop_time->[0]) > $opt_time_limit)
  930.     {
  931.       print "note: Aborting update loop because of timeout\n";
  932.       last;
  933.     }
  934.   }
  935.   $sth->finish;
  936.   # Check that everything except id3=0 was updated
  937.   # In principle we shouldn't time this in the update loop..
  938.   #
  939.   if (fetch_all_rows($dbh,$query="select * from bench1 where id3>=0") != 1)
  940.   {
  941.     if ($count == $total_rows)
  942.     {
  943.       print "Warning: Wrong information after update: Found '$row_count' rows, but should have been: 1\n";
  944.     }
  945.   }
  946.   #restore id3 to 0 <= id3 < $total_rows
  947.   $sth=$dbh->prepare("select id3 from bench1 where id3 < 0") or die $DBI::errstr;
  948.   $sth->execute or die $DBI::errstr;
  949.   while (@tmp = $sth->fetchrow_array)
  950.   {
  951.     $count++;
  952.     my $tmp1 = floor((0-$tmp[0])/10);
  953.     my $sth1 = $dbh->do("update bench1 set id3 = $tmp1 where id3 = $tmp[0]");
  954.   }
  955.   $sth->finish;
  956.   $end_time=new Benchmark;
  957.   $estimated=predict_query_time($loop_time,$end_time,\$count,$count,
  958.                 $opt_loop_count*6);
  959.   if ($estimated)
  960.   { print "Estimated time"; }
  961.   else
  962.   { print "Time"; }
  963.   print " for update_of_key ($count): " .
  964.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  965. }
  966.  
  967. if ($opt_fast && defined($server->{vacuum}))
  968. {
  969.   if ($opt_lock_tables)
  970.   {
  971.     do_query($dbh,"UNLOCK TABLES");
  972.   }
  973.   $server->vacuum(1,\$dbh,"bench1");
  974.   if ($opt_lock_tables)
  975.   {
  976.     $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  977.   }
  978. }
  979.  
  980. #
  981. # Testing some simple updates
  982. #
  983.  
  984. print "Testing update with key\n";
  985. $loop_time=new Benchmark;
  986. for ($i=0 ; $i < $opt_loop_count*3 ; $i++)
  987. {
  988.   $sth = $dbh->do("update bench1 set dummy1='updated' where id=$i and id2=$i") or die $DBI::errstr;
  989. }
  990.  
  991. $end_time=new Benchmark;
  992. print "Time for update_with_key (" . ($opt_loop_count*3) . "):  " .
  993.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  994.  
  995. $loop_time=new Benchmark;
  996. $count=0;
  997. for ($i=1 ; $i < $opt_loop_count*3 ; $i+=3)
  998. {
  999.   $sth = $dbh->do("update bench1 set dummy1='updated' where id=$i") or die $DBI::errstr;
  1000.   $end_time=new Benchmark;
  1001.   last if ($estimated=predict_query_time($loop_time,$end_time,\$i,$tests,
  1002.                      $opt_loop_count));
  1003. }
  1004. if ($estimated)
  1005. { print "Estimated time"; }
  1006. else
  1007. { print "Time"; }
  1008. print " for update_with_key_prefix (" . ($opt_loop_count) . "):  " .
  1009.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  1010.  
  1011. print "\nTesting update of all rows\n";
  1012. $loop_time=new Benchmark;
  1013. for ($i=0 ; $i < $small_loop_count ; $i++)
  1014. {
  1015.   $sth = $dbh->do("update bench1 set dummy1='updated $i'") or die $DBI::errstr;
  1016. }
  1017. $end_time=new Benchmark;
  1018. print "Time for update_big ($small_loop_count):  " .
  1019.   timestr(timediff($end_time, $loop_time),"all") . "\n";
  1020.  
  1021.  
  1022. #
  1023. # Testing left outer join
  1024. #
  1025.  
  1026. if ($limits->{'func_odbc_floor'} && $limits->{'left_outer_join'})
  1027. {
  1028.   if ($opt_lock_tables)
  1029.   {
  1030.     $sth = $dbh->do("LOCK TABLES bench1 a READ, bench1 b READ") || die $DBI::errstr;
  1031.   }
  1032.   print "\nTesting left outer join\n";
  1033.   $loop_time=new Benchmark;
  1034.   $count=0;
  1035.   for ($i=0 ; $i < $small_loop_count ; $i++)
  1036.   {
  1037.     $count+=fetch_all_rows($dbh,"select count(*) from bench1 as a left outer join bench1 as b on (a.id2=b.id3)");
  1038.   }
  1039.   $end_time=new Benchmark;
  1040.   print "Time for outer_join_on_key ($small_loop_count:$count):  " .
  1041.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1042.  
  1043.   $loop_time=new Benchmark;
  1044.   $count=0;
  1045.   for ($i=0 ; $i < $small_loop_count ; $i++)
  1046.   {
  1047.     $count+=fetch_all_rows($dbh,"select count(a.dummy1),count(b.dummy1) from bench1 as a left outer join bench1 as b on (a.id2=b.id3)");
  1048.   }
  1049.   $end_time=new Benchmark;
  1050.   print "Time for outer_join ($small_loop_count:$count):  " .
  1051.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1052.  
  1053.   $count=0;
  1054.   $loop_time=new Benchmark;
  1055.   for ($i=0 ; $i < $small_loop_count ; $i++)
  1056.   {
  1057.     $count+=fetch_all_rows($dbh,"select count(a.dummy1),count(b.dummy1) from bench1 as a left outer join bench1 as b on (a.id2=b.id3) where b.id3 is not null");
  1058.   }
  1059.   $end_time=new Benchmark;
  1060.   print "Time for outer_join_found ($small_loop_count:$count):  " .
  1061.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1062.  
  1063.   $count=$estimated=0;
  1064.   $loop_time=new Benchmark;
  1065.   for ($i=1 ; $i <= $small_loop_count ; $i++)
  1066.   {
  1067.     $count+=fetch_all_rows($dbh,"select count(a.dummy1),count(b.dummy1) from bench1 as a left outer join bench1 as b on (a.id2=b.id3) where b.id3 is null");
  1068.     $end_time=new Benchmark;
  1069.     last if ($estimated=predict_query_time($loop_time,$end_time,
  1070.                        \$count,$i,
  1071.                        $range_loop_count));
  1072.   }
  1073.   if ($estimated)
  1074.   { print "Estimated time"; }
  1075.   else
  1076.   { print "Time"; }
  1077.   print " for outer_join_not_found ($range_loop_count:$count):  " .
  1078.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1079.  
  1080.   if ($opt_lock_tables)
  1081.   {
  1082.     $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  1083.   }
  1084. }
  1085.  
  1086. if ($server->small_rollback_segment())
  1087. {
  1088.   $dbh->disconnect;                # close connection
  1089.   $dbh = $server->connect();
  1090. }
  1091.  
  1092. ###
  1093. ### Test speed of IN( value list)
  1094. ###
  1095.  
  1096. if ($limits->{'left_outer_join'})
  1097. {
  1098.   if ($opt_lock_tables)
  1099.   {
  1100.     $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
  1101.   }
  1102.   print "\n";
  1103.   do_many($dbh,$server->create("bench2",
  1104.                    ["id int NOT NULL"],
  1105.                    ["primary key (id)"]));
  1106.  
  1107.   $max_tests=min(($limits->{'query_size'}-50)/6, $opt_loop_count);
  1108.  
  1109.   if ($opt_lock_tables)
  1110.   {
  1111.     $sth = $dbh->do("LOCK TABLES bench1 READ, bench2 WRITE") ||
  1112.       die $DBI::errstr;
  1113.   }
  1114.   test_where_in("bench1","bench2","id",1,10);
  1115.   test_where_in("bench1","bench2","id",11,min(100,$max_tests));
  1116.   test_where_in("bench1","bench2","id",101,min(1000,$max_tests));
  1117.   if ($opt_lock_tables)
  1118.   {
  1119.     $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
  1120.   }
  1121.   $sth = $dbh->do("DROP TABLE bench2" . $server->{'drop_attr'}) ||
  1122.     die $DBI::errstr;
  1123.   if ($opt_lock_tables)
  1124.   {
  1125.     $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  1126.   }
  1127. }
  1128.  
  1129. ####
  1130. #### Test INSERT INTO ... SELECT
  1131. ####
  1132.  
  1133. if ($limits->{'insert_select'})
  1134. {
  1135.   if ($opt_lock_tables)
  1136.   {
  1137.     $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
  1138.   }
  1139.   print "\nTesting INSERT INTO ... SELECT\n";
  1140.   do_many($dbh,$server->create("bench2",
  1141.                    ["id int NOT NULL",
  1142.                 "id2 int NOT NULL",
  1143.                 "id3 int NOT NULL",
  1144.                 "dummy1 char(30)"],
  1145.                    ["primary key (id,id2)"]));
  1146.   do_many($dbh,$server->create("bench3",
  1147.                    ["id int NOT NULL",
  1148.                 "id2 int NOT NULL",
  1149.                 "id3 int NOT NULL",
  1150.                 "dummy1 char(30)"],
  1151.                    ["primary key (id,id2)",
  1152.                 "index index_id3 (id3)"]));
  1153.   $loop_time=new Benchmark;
  1154.   $sth = $dbh->do("INSERT INTO bench2 SELECT * from bench1") ||
  1155.     die $DBI::errstr;
  1156.   $end_time=new Benchmark;
  1157.   print "Time for insert_select_1_key (1):  " .
  1158.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1159.   $loop_time=new Benchmark;
  1160.   $sth = $dbh->do("INSERT INTO bench3 SELECT * from bench1") ||
  1161.     die $DBI::errstr;
  1162.   $end_time=new Benchmark;
  1163.   print "Time for insert_select_2_keys (1):  " .
  1164.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1165.   $loop_time=new Benchmark;
  1166.   $sth = $dbh->do("DROP TABLE bench2" . $server->{'drop_attr'}) ||
  1167.     die $DBI::errstr;
  1168.   $sth = $dbh->do("DROP TABLE bench3" . $server->{'drop_attr'}) ||
  1169.     die $DBI::errstr;
  1170.   $end_time=new Benchmark;
  1171.   print "Time for drop table(2): " .
  1172.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1173.  
  1174.   if ($opt_fast && defined($server->{vacuum}))
  1175.   {
  1176.     $server->vacuum(1,\$dbh);
  1177.   }
  1178.   if ($server->small_rollback_segment())
  1179.   {
  1180.     $dbh->disconnect;                # close connection
  1181.     $dbh = $server->connect();
  1182.   }
  1183.   if ($opt_lock_tables)
  1184.   {
  1185.     $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  1186.   }
  1187. }
  1188.  
  1189. ####
  1190. #### Do some deletes on the table
  1191. ####
  1192.  
  1193. if (!$opt_skip_delete)
  1194. {
  1195.   print "\nTesting delete\n";
  1196.   $loop_time=new Benchmark;
  1197.   $count=0;
  1198.   for ($i=0 ; $i < $opt_loop_count ; $i+=10)
  1199.   {
  1200.     $count++;
  1201.     $tmp=$opt_loop_count+$random[$i]; # $opt_loop_count*2 <= $tmp < $total_rows
  1202.     $dbh->do("delete from bench1 where id3=$tmp") or die $DBI::errstr;
  1203.   }
  1204.  
  1205.   $end_time=new Benchmark;
  1206.   print "Time for delete_key ($count): " .
  1207.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1208.  
  1209.   if ($server->small_rollback_segment())
  1210.   {
  1211.     $dbh->disconnect;                # close connection
  1212.     $dbh = $server->connect();
  1213.   }
  1214.  
  1215.   $count=0;
  1216.   $loop_time=new Benchmark;
  1217.   for ($i= 0 ; $i < $opt_loop_count ; $i+=$opt_loop_count/10)
  1218.   {
  1219.     $sth=$dbh->do("delete from bench1 where id3 >= 0 and id3 <= $i") or die $DBI::errstr;
  1220.     $count++;
  1221.   }
  1222.   $count+=2;
  1223.   if ($server->small_rollback_segment())
  1224.   {
  1225.     $dbh->disconnect;                # close connection
  1226.     $dbh = $server->connect();
  1227.   }
  1228.   $sth=$dbh->do("delete from bench1 where id3 >= 0 and id3 <= $opt_loop_count") or die $DBI::errstr;
  1229.   if ($server->small_rollback_segment())
  1230.   {
  1231.     $dbh->disconnect;                # close connection
  1232.     $dbh = $server->connect();
  1233.   }
  1234.  
  1235.   $sth=$dbh->do("delete from bench1 where id >= $opt_loop_count and id <= " . ($opt_loop_count*2) ) or die $DBI::errstr;
  1236.  
  1237.   if ($server->small_rollback_segment())
  1238.   {
  1239.     $dbh->disconnect;                # close connection
  1240.     $dbh = $server->connect();
  1241.   }
  1242.   if ($opt_fast)
  1243.   {
  1244.     $sth=$dbh->do("delete from bench1") or die $DBI::errstr;
  1245.   }
  1246.   else
  1247.   {
  1248.     $sth = $dbh->do("delete from bench1 where id3 < " . ($total_rows)) or die $DBI::errstr;
  1249.   }
  1250.  
  1251.   $end_time=new Benchmark;
  1252.   print "Time for delete_range ($count): " .
  1253.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  1254.  
  1255.   if ($opt_lock_tables)
  1256.   {
  1257.     $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
  1258.   }
  1259.   $sth = $dbh->do("drop table bench1" . $server->{'drop_attr'}) or die $DBI::errstr;
  1260. }
  1261.  
  1262. if ($server->small_rollback_segment())
  1263. {
  1264.   $dbh->disconnect;                # close connection
  1265.   $dbh = $server->connect();
  1266. }
  1267. if ($opt_fast && defined($server->{vacuum}))
  1268. {
  1269.   $server->vacuum(1,\$dbh);
  1270. }
  1271.  
  1272.  
  1273. keys_test:
  1274. #
  1275. # Test of insert in table with many keys
  1276. # This test assumes that the server really create the keys!
  1277. #
  1278.  
  1279. my @fields=(); my @keys=();
  1280. $keys=min($limits->{'max_index'},16);          # 16 is more than enough
  1281. $seg= min($limits->{'max_index_parts'},$keys,16); # 16 is more than enough
  1282.  
  1283. print "Insert into table with $keys keys and with a primary key with $seg parts\n";
  1284.  
  1285. # Make keys on the most important types
  1286. @types=(0,0,0,1,0,0,0,1,1,1,1,1,1,1,1,1,1);    # A 1 for each char field
  1287. push(@fields,"field1 tinyint not null");
  1288. push(@fields,"field_search tinyint not null");
  1289. push(@fields,"field2 mediumint not null");
  1290. push(@fields,"field3 smallint not null");
  1291. push(@fields,"field4 char(16) not null");
  1292. push(@fields,"field5 integer not null");
  1293. push(@fields,"field6 float not null");
  1294. push(@fields,"field7 double not null");
  1295. for ($i=8 ; $i <= $keys ; $i++)
  1296. {
  1297.   push(@fields,"field$i char(6) not null");    # Should be relatively fair
  1298. }
  1299.  
  1300. # First key contains many segments
  1301. $query="primary key (";
  1302. for ($i= 1 ; $i <= $seg ; $i++)
  1303. {
  1304.   $query.= "field$i,";
  1305. }
  1306. substr($query,-1)=")";
  1307. push (@keys,$query);
  1308. push (@keys,"index index2 (field_search)");
  1309.  
  1310. #Create other keys
  1311. for ($i=3 ; $i <= $keys ; $i++)
  1312. {
  1313.   push(@keys,"index index$i (field$i)");
  1314. }
  1315.  
  1316. do_many($dbh,$server->create("bench1",\@fields,\@keys));
  1317. if ($opt_lock_tables)
  1318. {
  1319.   $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  1320. }
  1321.  
  1322. if ($server->small_rollback_segment())
  1323. {
  1324.   $dbh->disconnect;                # close connection
  1325.   $dbh = $server->connect();
  1326. }
  1327.  
  1328. $loop_time=new Benchmark;
  1329. if ($opt_fast && $server->{transactions})
  1330. {
  1331.   $dbh->{AutoCommit} = 0;
  1332. }
  1333.  
  1334. $fields=$#fields;
  1335. if (($opt_fast || $opt_fast_insert) && $server->{'limits'}->{'insert_multi_value'})
  1336. {
  1337.   $query_size=$server->{'limits'}->{'query_size'};
  1338.   $query="insert into bench1 values ";
  1339.   $res=$query;
  1340.   for ($i=0; $i < $many_keys_loop_count; $i++)
  1341.   {
  1342.     $id= $i & 127;
  1343.     $rand=$random[$i];
  1344.     $tmp="($id,$id,$rand," . ($i & 32766) . ",'ABCDEF$rand',0,$rand,$rand.0,";
  1345.  
  1346.     for ($j=8; $j <= $fields ; $j++)
  1347.     {
  1348.       $tmp.= ($types[$j] == 0) ? "$rand," : "'$rand',";
  1349.     }
  1350.     substr($tmp,-1)=")";
  1351.     if (length($tmp)+length($res) < $query_size)
  1352.     {
  1353.       $res.= $tmp . ",";
  1354.     }
  1355.     else
  1356.     {
  1357.       $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  1358.       $res=$query . $tmp . ",";
  1359.     }
  1360.   }
  1361.   $sth = $dbh->do(substr($res,0,length($res)-1)) or die $DBI::errstr;
  1362. }
  1363. else
  1364. {
  1365.   for ($i=0; $i < $many_keys_loop_count; $i++)
  1366.   {
  1367.     $id= $i & 127;
  1368.     $rand=$random[$i];
  1369.     $query="insert into bench1 values ($id,$id,$rand," . ($i & 32767) .
  1370.       ",'ABCDEF$rand',0,$rand,$rand.0,";
  1371.  
  1372.     for ($j=8; $j <= $fields ; $j++)
  1373.     {
  1374.       $query.= ($types[$j] == 0) ? "$rand," : "'$rand',";
  1375.     }
  1376.     substr($query,-1)=")";
  1377.     print "query1: $query\n" if ($opt_debug);
  1378.     $dbh->do($query) or die "Got error $DBI::errstr with query: $query\n";
  1379.   }
  1380. }
  1381.  
  1382. if ($opt_fast && $server->{transactions})
  1383. {
  1384.   $dbh->commit;
  1385.   $dbh->{AutoCommit} = 1;
  1386. }
  1387.  
  1388. $end_time=new Benchmark;
  1389. print "Time for insert_key ($many_keys_loop_count): " .
  1390.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  1391.  
  1392. if ($server->small_rollback_segment())
  1393. {
  1394.   $dbh->disconnect;                # close connection
  1395.   $dbh = $server->connect();
  1396. }
  1397. if ($opt_fast && defined($server->{vacuum}))
  1398. {
  1399.   if ($opt_lock_tables)
  1400.   {
  1401.     do_query($dbh,"UNLOCK TABLES");
  1402.   }
  1403.   $server->vacuum(1,\$dbh,"bench1");
  1404.   if ($opt_lock_tables)
  1405.   {
  1406.     $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  1407.   }
  1408. }
  1409.  
  1410. #
  1411. # update one key of the above
  1412. #
  1413.  
  1414. print "Testing update of keys\n";
  1415. $loop_time=new Benchmark;
  1416.  
  1417. if ($opt_fast && $server->{transactions})
  1418. {
  1419.   $dbh->{AutoCommit} = 0;
  1420. }
  1421.  
  1422. for ($i=0 ; $i< 256; $i++)
  1423. {
  1424.   $dbh->do("update bench1 set field5=1 where field_search=$i")
  1425.     or die "Got error $DBI::errstr with query: update bench1 set field5=1 where field_search=$i\n";
  1426. }
  1427.  
  1428. if ($opt_fast && $server->{transactions})
  1429. {
  1430.   $dbh->commit;
  1431.   $dbh->{AutoCommit} = 1;
  1432. }
  1433.  
  1434. $end_time=new Benchmark;
  1435. print "Time for update_of_primary_key_many_keys (256): " .
  1436.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  1437.  
  1438. if ($server->small_rollback_segment())
  1439. {
  1440.   $dbh->disconnect;                # close connection
  1441.   $dbh = $server->connect();
  1442. }
  1443. if ($opt_fast && defined($server->{vacuum}))
  1444. {
  1445.   if ($opt_lock_tables)
  1446.   {
  1447.     do_query($dbh,"UNLOCK TABLES");
  1448.   }
  1449.   $server->vacuum(1,\$dbh,"bench1");
  1450.   if ($opt_lock_tables)
  1451.   {
  1452.     $sth = $dbh->do("LOCK TABLES bench1 WRITE") || die $DBI::errstr;
  1453.   }
  1454. }
  1455.  
  1456. if ($server->small_rollback_segment())
  1457. {
  1458.   $dbh->disconnect;                # close connection
  1459.   $dbh = $server->connect();
  1460. }
  1461.  
  1462. #
  1463. # Delete everything from table
  1464. #
  1465.  
  1466. print "Deleting rows from the table\n";
  1467. $loop_time=new Benchmark;
  1468. $count=0;
  1469.  
  1470. for ($i=0 ; $i < 128 ; $i++)
  1471. {
  1472.   $count++;
  1473.   $dbh->do("delete from bench1 where field_search = $i") or die $DBI::errstr;
  1474. }
  1475.  
  1476. $end_time=new Benchmark;
  1477. print "Time for delete_big_many_keys ($count): " .
  1478. timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  1479.  
  1480. if ($opt_lock_tables)
  1481. {
  1482.   $sth = $dbh->do("UNLOCK TABLES") || die $DBI::errstr;
  1483. }
  1484.  
  1485. print "Deleting everything from table\n";
  1486. $count=1;
  1487. if ($opt_fast)
  1488. {
  1489.   $query= ($limits->{'truncate_table'} ? "truncate table bench1" :
  1490.          "delete from bench1");
  1491.   $dbh->do($query) or die $DBI::errstr;
  1492. }
  1493. else
  1494. {
  1495.   $dbh->do("delete from bench1 where field1 > 0") or die $DBI::errstr;
  1496. }
  1497.  
  1498. $end_time=new Benchmark;
  1499. print "Time for delete_all_many_keys ($count): " .
  1500.   timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  1501.  
  1502. $sth = $dbh->do("drop table bench1" . $server->{'drop_attr'}) or die $DBI::errstr;
  1503. if ($opt_fast && defined($server->{vacuum}))
  1504. {
  1505.   $server->vacuum(1,\$dbh);
  1506. }
  1507.  
  1508. #
  1509. # Test multi value inserts if the server supports it
  1510. #
  1511.  
  1512. if ($limits->{'insert_multi_value'})
  1513. {
  1514.   $query_size=$limits->{'query_size'}; # Same limit for all databases
  1515.  
  1516.   $sth = $dbh->do("drop table bench1" . $server->{'drop_attr'});
  1517.   do_many($dbh,$server->create("bench1",
  1518.                    ["id int NOT NULL",
  1519.                 "id2 int NOT NULL",
  1520.                 "id3 int NOT NULL",
  1521.                 "dummy1 char(30)"],
  1522.                    ["primary key (id,id2)",
  1523.                    "index index_id3 (id3)"]));
  1524.  
  1525.   $loop_time=new Benchmark;
  1526.  
  1527.   if ($opt_lock_tables)
  1528.   {
  1529.     $sth = $dbh->do("LOCK TABLES bench1 write") || die $DBI::errstr;
  1530.   }
  1531.   if ($opt_fast && $server->{transactions})
  1532.   {
  1533.     $dbh->{AutoCommit} = 0;
  1534.   }
  1535.  
  1536.   print "Inserting $opt_loop_count rows with multiple values\n";
  1537.   $query="insert into bench1 values ";
  1538.   $res=$query;
  1539.   for ($i=0 ; $i < $opt_loop_count ; $i++)
  1540.   {
  1541.     my $tmp= "($i,$i,$i,'EFGHIJKLM'),";
  1542.     if (length($i)+length($res) < $query_size)
  1543.     {
  1544.       $res.= $tmp;
  1545.     }
  1546.     else
  1547.     {
  1548.       do_query($dbh,substr($res,0,length($res)-1));
  1549.       $res=$query .$tmp;
  1550.     }
  1551.   }
  1552.   do_query($dbh,substr($res,0,length($res)-1));
  1553.  
  1554.   if ($opt_lock_tables)
  1555.   {
  1556.     $sth = $dbh->do("UNLOCK TABLES ") || die $DBI::errstr;
  1557.   }
  1558.   if ($opt_fast && $server->{transactions})
  1559.   {
  1560.     $dbh->commit;
  1561.     $dbh->{AutoCommit} = 1;
  1562.   }
  1563.  
  1564.   $end_time=new Benchmark;
  1565.   print "Time for multiple_value_insert (" . ($opt_loop_count) . "): " .
  1566.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  1567.  
  1568.   if ($opt_lock_tables)
  1569.   {
  1570.     $sth = $dbh->do("UNLOCK TABLES ") || die $DBI::errstr;
  1571.   }
  1572.  
  1573.   # A big table may take a while to drop
  1574.   $loop_time=new Benchmark;
  1575.   $sth = $dbh->do("drop table bench1" . $server->{'drop_attr'}) or die $DBI::errstr;
  1576.   $end_time=new Benchmark;
  1577.   print "Time for drop table(1): " .
  1578.     timestr(timediff($end_time, $loop_time),"all") . "\n\n";
  1579. }
  1580.  
  1581. ####
  1582. #### End of benchmark
  1583. ####
  1584.  
  1585. $dbh->disconnect;                # close connection
  1586.  
  1587. end_benchmark($start_time);
  1588.  
  1589. ###
  1590. ### Some help functions
  1591. ###
  1592.  
  1593.  
  1594. # Do some sample selects on direct key
  1595. # First select finds a row, the second one doesn't find.
  1596.  
  1597. sub check_select_key
  1598. {
  1599.   my ($sel_columns,$column,$check)= @_;
  1600.   my ($loop_time,$end_time,$i,$tmp_var,$tmp,$count,$row_count,$estimated);
  1601.  
  1602.   $estimated=0;
  1603.   $loop_time=new Benchmark;
  1604.   $count=0;
  1605.   for ($i=1 ; $i <= $opt_read_key_loop_count; $i++)
  1606.   {
  1607.     $count+=2;
  1608.     $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  1609.     $tmp=$tmpvar % ($total_rows);
  1610.     fetch_all_rows($dbh,"select $sel_columns from bench1 where $column=$tmp")
  1611.       or die $DBI::errstr;
  1612.     $tmp+=$total_rows;
  1613.     defined($row_count=fetch_all_rows($dbh,"select $sel_columns from bench1 where $column=$tmp")) or die $DBI::errstr;
  1614.     die "Found $row_count rows on impossible id: $tmp\n" if ($row_count);
  1615.     $end_time=new Benchmark;
  1616.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i,
  1617.                        $opt_loop_count));
  1618.   }
  1619.   if ($estimated)
  1620.   { print "Estimated time"; }
  1621.   else
  1622.   { print "Time"; }
  1623.   print " for $check ($count): " .
  1624.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1625. }
  1626.  
  1627. # Same as above, but select on 2 columns
  1628.  
  1629. sub check_select_key2
  1630. {
  1631.   my ($sel_columns,$column,$column2,$check)= @_;
  1632.   my ($loop_time,$end_time,$i,$tmp_var,$tmp,$count,$row_count,$estimated);
  1633.  
  1634.   $estimated=0;
  1635.   $loop_time=new Benchmark;
  1636.   $count=0;
  1637.   for ($i=1 ; $i <= $opt_read_key_loop_count; $i++)
  1638.   {
  1639.     $count+=2;
  1640.     $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  1641.     $tmp=$tmpvar % ($total_rows);
  1642.     fetch_all_rows($dbh,"select $sel_columns from bench1 where $column=$tmp and $column2=$tmp")
  1643.       or die $DBI::errstr;
  1644.     $tmp+=$total_rows;
  1645.     defined($row_count=fetch_all_rows($dbh,"select $sel_columns from bench1 where $column=$tmp and $column2=$tmp")) or die $DBI::errstr;
  1646.     die "Found $row_count rows on impossible id: $tmp\n" if ($row_count);
  1647.     $end_time=new Benchmark;
  1648.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$i,
  1649.                        $opt_loop_count));
  1650.   }
  1651.   if ($estimated)
  1652.   { print "Estimated time"; }
  1653.   else
  1654.   { print "Time"; }
  1655.   print " for $check ($count): " .
  1656.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1657. }
  1658.  
  1659. #
  1660. # Search using some very simple queries
  1661. #
  1662.  
  1663. sub check_select_range
  1664. {
  1665.   my ($column,$check)= @_;
  1666.   my ($loop_time,$end_time,$i,$tmp_var,$tmp,$query,$rows,$estimated);
  1667.  
  1668.   $estimated=0;
  1669.   $loop_time=new Benchmark;
  1670.   $found=$count=0;
  1671.   for ($test=1 ; $test <= $range_loop_count; $test++)
  1672.   {
  1673.     $count+=$#Q+1;
  1674.     for ($i=0 ; $i < $#Q ; $i+=2)
  1675.     {
  1676.       $query=$Q[$i];
  1677.       $rows=$Q[$i+1];
  1678.       $query =~ s/!id!/$column/g;
  1679.       if (($row_count=fetch_all_rows($dbh,$query)) != $rows)
  1680.       {
  1681.     if ($row_count == undef())
  1682.     {
  1683.       die "Got error: $DBI::errstr when executing $query\n";
  1684.     }
  1685.     die "'$query' returned wrong number of rows: $row_count instead of $rows\n";
  1686.       }
  1687.       $found+=$row_count;
  1688.     }
  1689.     $end_time=new Benchmark;
  1690.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$test,
  1691.                        $range_loop_count));
  1692.   }
  1693.   if ($estimated)
  1694.   { print "Estimated time"; }
  1695.   else
  1696.   { print "Time"; }
  1697.   print " for $check ($count:$found): " .
  1698.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1699. }
  1700.  
  1701.  
  1702. #
  1703. # SELECT * from bench where col=x or col=x or col=x ...
  1704.  
  1705.  
  1706. sub check_or_range
  1707. {
  1708.   my ($column,$check)= @_;
  1709.   my ($loop_time,$end_time,$i,$tmp_var,$tmp,$columns,$estimated,$found,
  1710.       $or_part,$count,$loop_count);
  1711.  
  1712.   $columns=min($limits->{'max_columns'},50,($limits->{'query_size'}-50)/13);
  1713.   $columns=$columns- ($columns % 4); # Make Divisible by 4
  1714.  
  1715.   $estimated=0;
  1716.   $loop_time=new Benchmark;
  1717.   $found=0;
  1718.   # The number of tests must be divisible by the following
  1719.   $tmp= $limits->{'func_extra_in_num'} ? 15 : 10; 
  1720.   # We need to calculate the exact number of test to make 'Estimated' right
  1721.   $loop_count=$range_loop_count*10+$tmp-1;
  1722.   $loop_count=$loop_count- ($loop_count % $tmp);
  1723.   
  1724.   for ($count=0 ; $count < $loop_count ; )
  1725.   {
  1726.     for ($rowcnt=0; $rowcnt <= $columns; $rowcnt+= $columns/4)
  1727.     {
  1728.       my $query="select * from bench1 where ";
  1729.       my $or_part= "$column = 1";
  1730.       $count+=2;
  1731.  
  1732.       for ($i=1 ; $i < $rowcnt ; $i++)
  1733.       {
  1734.     $tmpvar^= ((($tmpvar + 63) + $i)*3 % $opt_loop_count);
  1735.     $tmp=$tmpvar % ($opt_loop_count*4);
  1736.     $or_part.=" or $column=$tmp";
  1737.       }
  1738.       print $query . $or_part . "\n" if ($opt_debug);
  1739.       ($rows=fetch_all_rows($dbh,$query . $or_part)) or die $DBI::errstr;
  1740.       $found+=$rows;
  1741.  
  1742.       if ($limits->{'func_extra_in_num'})
  1743.       {
  1744.     my $in_part=$or_part;    # Same query, but use 'func_extra_in_num' instead.
  1745.     $in_part=~ s/ = / IN \(/;
  1746.     $in_part=~ s/ or $column=/,/g;
  1747.     $in_part.= ")";
  1748.     fetch_all_rows($dbh,$query . $in_part) or die $DBI::errstr;
  1749.     $count++;
  1750.       }
  1751.       # Do it a little harder by setting a extra range
  1752.       defined(($rows=fetch_all_rows($dbh,"$query($or_part) and $column < 10"))) or die $DBI::errstr;
  1753.       $found+=$rows;
  1754.     }
  1755.     $end_time=new Benchmark;
  1756.     last if ($estimated=predict_query_time($loop_time,$end_time,\$count,$count,
  1757.                        $loop_count));
  1758.   }
  1759.  
  1760.   if ($estimated)
  1761.   { print "Estimated time"; }
  1762.   else
  1763.   { print "Time"; }
  1764.   print " for $check ($count:$found): " .
  1765.     timestr(timediff($end_time, $loop_time),"all") . "\n";
  1766. }
  1767.  
  1768. #
  1769. # General test of SELECT ... WHERE id in(value-list)
  1770. #
  1771.  
  1772. sub test_where_in
  1773. {
  1774.   my ($t1,$t2,$id,$from,$to)= @_;
  1775.  
  1776.   return if ($from >= $to);
  1777.  
  1778.   $query="SELECT $t1.* FROM $t1 WHERE $id IN (";
  1779.   for ($i=1 ; $i <= $to ; $i++)
  1780.   {
  1781.     $query.="$i,";
  1782.   }
  1783.   $query=substr($query,0,length($query)-1) . ")";
  1784.  
  1785.   # Fill join table to have the same id's as 'query'
  1786.   for ($i= $from ; $i <= $to ; $i++)
  1787.   {
  1788.     $dbh->do("insert into $t2 values($i)") or die $DBI::errstr;
  1789.   }
  1790.   if ($opt_fast && defined($server->{vacuum}))
  1791.   {
  1792.     $server->vacuum(1,\$dbh,"bench1");
  1793.   }
  1794.  
  1795.   time_fetch_all_rows("Testing SELECT ... WHERE id in ($to values)",
  1796.               "select_in", $query, $dbh,
  1797.               $range_loop_count);
  1798.   time_fetch_all_rows(undef, "select_join_in",
  1799.               "SELECT $t1.* FROM $t2 left outer join $t1 on ($t1.$id=$t2.$id)",
  1800.                $dbh, $range_loop_count);
  1801. }
  1802.